home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / General / CW TCL port package / Template Munger / Source / MungeFiles.c < prev    next >
Text File  |  1994-05-30  |  11KB  |  429 lines

  1. /*
  2.  * munge.c
  3.  */
  4.  
  5. #include <string.h>
  6.  
  7. extern int * sprintf( char *, const char *, ... ) ;
  8. unsigned char * C2P ( char* ) ;
  9.  
  10. extern void Idle ( void ) ;
  11. extern short vRefNum ;
  12. void MungeFile ( short vRef , long parID , unsigned char * fn, Boolean isTemplateDefn ) ;
  13. void MungeFolder ( long parID ) ;
  14. extern void Message ( unsigned char * ) ;
  15.  
  16. Boolean OpenOutfile();
  17. void CloseOutfile();
  18. void OutJunkChar(char theChar);
  19. Boolean OutToken(char* theToken);
  20. void OutNewLine();
  21. void EndTemplateDeclaration();
  22. void StartTemplateDefn();
  23. void EndTemplateDefn();
  24.  
  25. CInfoPBRec rec ;
  26. short err ;
  27. Str63 name ;
  28. Str255 str ;
  29.  
  30. Str63 outFileName;                    // name of template macro file name (typically ___.tm.h)
  31. Str63 defnFileName;                    // name of template definition file name (typically ___.tem)
  32.  
  33.  
  34. /*    0 == whitespace
  35.     1 == line feed chars
  36.     2 == digit
  37.     3 == colon
  38.     4 == letter
  39.     5 == bracket {
  40.     6 == bracket }
  41.     7 == angle bracket <
  42.     8 == angle bracket >
  43.     9 == start of comment
  44.     10 == left paren (, used to identify constructors
  45.     */
  46.  
  47. char ch_type [ ] = {
  48. /*        0,    1,    2,    3,    4,    5,    6,    7,    8,    9,    A,    B,    C,    D,    E,    F */
  49. /* 0 */    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,    0,    0,
  50. /* 1 */    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  51. /* 2 */    0,    0,    0,    9,    0,    0,    0,    0,   10,    0,    0,    0,    0,    0,    0,    9,
  52. /* 3 */    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    3,    0,    7,    0,    8,    0,
  53. /* 4 */    0,    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
  54. /* 5 */    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,    0,    0,    0,    0,    4,
  55. /* 6 */    0,    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
  56. /* 7 */    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,    4,    5,    0,    6,    0,    0,
  57. /* 8 */    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  58. /* 9 */    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  59. /* A */    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  60. /* B */    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  61. /* C */    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  62. /* D */    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  63. /* E */    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  64. /* F */    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0
  65. } ;
  66.  
  67. static void
  68. CopyP ( unsigned char * from , unsigned char * to ) {
  69.     BlockMove ( from , to , 1 + * from ) ;
  70. }
  71.  
  72.  
  73. static void
  74. ConcP ( unsigned char * to , unsigned char * tail ) {
  75.  
  76. short len = * tail ;
  77.     if ( len + * to > 255 ) {
  78.         len = 255 - * to ;
  79.     }
  80.     BlockMove ( tail + 1 , to + * to + 1 , len ) ;
  81.     * to += len ;
  82. }
  83.  
  84.  
  85. unsigned char *
  86. C2P ( char * c ) {
  87. int len = strlen ( c ) ;
  88.     if ( len ) {
  89.         BlockMove ( c , c + 1 , len ) ;
  90.     }
  91.     * c = len ;
  92.     return ( unsigned char * ) c ;
  93. }
  94.  
  95.  
  96. void
  97. ErrMsg ( unsigned char * why , unsigned char * file , short code ) {
  98.  
  99. Str15 nn ;
  100. long tick ;
  101. static long lastBeep = 0 ;
  102.  
  103.     NumToString ( code , nn ) ;
  104.     CopyP ( "\p ERROR " , str ) ;
  105.     ConcP ( str , why ) ;
  106.     ConcP ( str , "\p " ) ;
  107.     ConcP ( str , nn ) ;
  108.     ConcP ( str , "\p\r" ) ;
  109.     Message ( str ) ;
  110.     tick = TickCount ( ) + 5 ;
  111.     if ( lastBeep < tick - 600 ) { /* Only beep every 10 seconds if lots of errors */
  112.         SysBeep ( 20 ) ;
  113.         lastBeep = tick ;
  114.     }
  115. }
  116.  
  117.  
  118. static long
  119. token ( Handle text , long pos , long end , char * tok , long * before, Boolean inTemplateDef ) {
  120.  
  121. char type ;
  122.  
  123.     while ( pos < end ) {
  124.         while ( ! ch_type [ ( * text ) [ pos ] ] && pos < end ) { // Skip junk
  125.             if (inTemplateDef)
  126.                 OutJunkChar((*text) [pos]);            // pass junk chars to template file
  127.             pos ++ ;
  128.         }
  129.         * before = pos ;
  130.         * tok = ( * text ) [ pos ] ; // First token char
  131.         pos ++ ;
  132.         type = ch_type [ * tok ] ;
  133.         tok ++ ;
  134.         if (type == 9) {                            // •• ES: comment parsing
  135.             if (((*text)[pos] == '/') || ((*text)[pos] == '*')) {
  136.                 *(tok++) = (*text)[pos++];
  137.                 *tok = 0;
  138.                 return pos;
  139.             }
  140.         }
  141.         if ( type == 1 ) { // line break
  142.             * tok = 0 ;
  143.             return pos ;
  144.         }
  145.         while ( pos < end ) {
  146.         char xTyp = ch_type [ ( * text ) [ pos ] ] ;
  147.             if ( ( xTyp != type ) &&
  148.                 ! ( type == 4 && xTyp == 2 ) ) { // Identifier number
  149.                 * tok = 0 ;
  150.                 return pos ;
  151.             }
  152.             * ( tok ++ ) = ( * text ) [ pos ++ ] ;
  153.             if (type == 9) {                    // comment: restrict to 2 characters
  154.                 break;
  155.             }
  156.         }
  157.     }
  158.     * tok = 0 ;
  159.     return end ;
  160. }
  161.  
  162.  
  163. static int
  164. Replace ( Handle text , long pos , long len , char * with ) {
  165.     Munger ( text , pos , NULL , len , with , strlen ( with ) ) ;
  166.     return strlen ( with ) - len ;
  167. }
  168.  
  169.  
  170. /* This function contains the total text of a TEXT file. */
  171. /* The contents of the handle will be re-written to disk when done if true returned. */
  172. /* Call Idle ( ) now and then for lengthy tasks */
  173.  
  174. // ES modified to look for template definitions
  175. // uses routines in MakeTemplate.c to write macro files
  176. // DOES NOT change source code
  177.  
  178. static void
  179. MungeHandle ( Handle text , short vRef , long parID, Boolean isTemplateDefn ) {
  180.  
  181. long end = GetHandleSize ( text ) ;
  182. long pos = 0 ;
  183. char tok [ 256 ] ;
  184. char other [ 256 ] ;
  185. long before = 0 ;
  186. long level = 0 ;
  187. long oldPos ;
  188. long oldBefore ;
  189. int line = 1 ;
  190. Boolean chng = 0 ;
  191. Boolean tempFileReady = 0;                // true if template file has been specified
  192. Boolean inTemplateDef = 0;                // flag if macro template file open
  193. Boolean inLineComment = 0;                // true if // encountered
  194. Boolean inCComment = 0;                    // true if /* encountered */
  195.  
  196.     if (isTemplateDefn)
  197.         StartTemplateDefn();
  198.  
  199.     tok [ 0 ] = 0 ;
  200.     while ( pos < end ) {
  201.         oldPos = pos ;
  202.         oldBefore = before ;
  203.         tok [ 0 ] = 0 ;
  204.         if (inCComment) {                        // •• ES: special handling for /* */ type comments
  205.             while (pos < end) {
  206.                 char tChar = (*text) [pos++];
  207.                 if (tChar == 0x0D) {                // new line?
  208.                     inLineComment = 0;
  209.                     line ++ ;
  210.                     if (!(line % 10))
  211.                         Idle();
  212.                 } else if (tChar == '*') {            // done yet?
  213.                     if ((pos < end) && ((*text) [pos] == '/')) {
  214.                         inCComment = 0;
  215.                         pos++;
  216.                         break;
  217.                     }
  218.                 }
  219.             }
  220.             continue;
  221.         }
  222.         pos = token ( text , pos , end , tok , & before, inTemplateDef || isTemplateDefn) ;
  223.         if ( ! tok [ 0 ] ) {
  224.             break ;
  225.         }
  226.         if ( ch_type [ tok [ 0 ] ] == 1 ) {
  227.             inLineComment = 0;
  228.             if (inTemplateDef || isTemplateDefn)
  229.                 OutNewLine();
  230.             line ++ ;
  231.             if ( ! ( line % 10 ) ) {
  232.                 Idle ( ) ;
  233.             }
  234.             continue;                        // no reason to continue parsing
  235.         }
  236.         if (inLineComment) {
  237.             if (!strcmp(tok, "__TEMPLATE__")) {    // •• ES: look for template hints
  238.                 if (inTemplateDef) {
  239.                     sprintf(other, "\r• Error Line %d: nested template declarations ", line );
  240.                     Message(C2P(other));
  241.                 } else {
  242.                     char* p;
  243.                     while ((pos < end) && ((*text) [pos] == ' '))
  244.                         pos++;                    // skip spaces
  245.  
  246.                     p = (char*) outFileName;            // collect output file name
  247.                     while ((pos < end) &&  ((*text) [pos] != ' ') &&  ((*text) [pos] != 0x0D))
  248.                         *p++ = ((*text) [pos++]);
  249.                     *p = 0;
  250.                     
  251.                     while ((pos < end) && ((*text) [pos] == ' '))
  252.                         pos++;                    // skip spaces
  253.  
  254.                     p = (char*) defnFileName;            // collect definition file name
  255.                     while ((pos < end) &&  ((*text) [pos] != ' ') &&  ((*text) [pos] != 0x0D))
  256.                         *p++ = ((*text) [pos++]);
  257.                     *p = 0;
  258.  
  259.                     C2P((char*) outFileName);
  260.                     C2P((char*) defnFileName);
  261.  
  262.                     tempFileReady = true;
  263.                 }
  264.             }
  265.             continue;                            // ignore all other syntax (it's a comment, after all!)
  266.         }
  267.         if (ch_type[tok[0]] == 9) {                // •• ES: parse for comments
  268.             if (tok[0] == '/') {
  269.                 if (tok[1] == '/') {                // strcmp wouldn't work here (in case characters follow comment)
  270.                     inLineComment = true;
  271.                     continue;
  272.                 } else if (tok[1] == '*') {
  273.                     inCComment = true;
  274.                     continue;
  275.                 }
  276.             } else if (tok[0] == '#') {                // need to ignore all preprocessor declarations
  277.                 inLineComment = true;            // treat them as line comments
  278.                 continue;                        // don’t parse any further
  279.             }
  280.         }
  281.         
  282.         if (!isTemplateDefn) {
  283.             if ( level ) {
  284.                 if ( ! strcmp ( tok , "{" ) ) {
  285.                     level ++ ;
  286.                 } else if ( ! strcmp ( tok , "}" ) ) {
  287.                     level -- ;
  288.                     if ((!level) && inTemplateDef) {                // •• ES: finish template declaration
  289.                         EndTemplateDeclaration();
  290.                         inTemplateDef = false;
  291.                         if (defnFileName[0] != 0)
  292.                             MungeFile(vRef, parID, defnFileName, true);    // recursive call to this routine – neat, huh?
  293.                         CloseOutfile();
  294.                     }
  295.                 }
  296.             } else { // no level - set context ?
  297.                 if ( ! strcmp ( tok, "template" ) ) {
  298.                     if (!tempFileReady) {
  299.                         sprintf(other, "\r• Warning Line %d: template declaration without __TEMPLATE__ " , line ) ;
  300.                         Message(C2P(other));
  301.                     } else {
  302.                         tempFileReady = false;
  303.                         inTemplateDef = true;
  304.                         if (OpenOutfile()) {            // start an output file
  305.                             ErrMsg("\pCreating", outFileName, err);
  306.                             inTemplateDef = false;
  307.                         }
  308.                     }
  309.                 } else if ( ! strcmp ( tok , "{" ) ) {
  310.                     level ++ ;
  311.                 } else if ( ! strcmp ( tok , "}" ) ) {
  312.                     sprintf ( other , "\r• Error Line %d: level < 0 " , line ) ;
  313.                     Message ( C2P ( other ) ) ;
  314.                 }
  315.             }
  316.         }
  317.  
  318.         if (inTemplateDef || isTemplateDefn)                    // valid token, echo tokens to macro file
  319.             if (!OutToken(tok)) {
  320.                 sprintf(other, "\r• Error Line %d: invalid template declaration", line);
  321.                 Message(C2P(other));
  322.             }
  323.  
  324.     }
  325.  
  326.     // make sure we haven't left a file hanging
  327.     
  328.     if (inTemplateDef) {
  329.         CloseOutfile();
  330.         sprintf(other, "\r• Error Line %d: unfinished template declaration ", line );
  331.         Message(C2P(other));
  332.     }
  333.     
  334.     if (isTemplateDefn)
  335.         EndTemplateDefn();
  336.     
  337. }
  338.  
  339.  
  340. static void
  341. MungeFile ( short vRef , long parID , unsigned char * fn, Boolean isTemplateDefn ) {
  342.  
  343. Handle text ;
  344. short ref = 0 ;
  345. long size ;
  346. Boolean doWrite ;
  347. char other [255];
  348.  
  349.     if (!isTemplateDefn) {
  350.         if ((fn[fn[0]-1] != '.') || (fn[fn[0]] != 'h')) {        // only read ".h" files, unless reading as template declaration
  351.             return;
  352.         }
  353.         Message ( fn ) ;
  354.     }
  355.  
  356.     err = HOpenDF ( vRef , parID , fn , fsRdWrPerm , & ref ) ;
  357.     if ( err ) {
  358.         ErrMsg ( "\pOpening" , fn , err ) ;
  359.         return ;
  360.     }
  361.     err = GetEOF ( ref , & size ) ;
  362.     if ( ! err ) {
  363.         err = SetFPos ( ref , fsFromStart , 0L ) ;
  364.     }
  365.     if ( err ) {
  366.         ErrMsg ( "\pStarting" , fn , err ) ;
  367.         FSClose ( ref ) ;
  368.         return ;
  369.     }
  370.     text = NewHandle ( size ) ;
  371.     if ( ! text ) {
  372.         ErrMsg ( "\pAllocating" , fn , MemError ( ) ) ;
  373.         FSClose ( ref ) ;
  374.         return ;
  375.     }
  376.     HLock ( text ) ;
  377.     err = FSRead ( ref , & size , * text ) ;
  378.     if ( err ) {
  379.         ErrMsg ( "\pReading" , fn , err ) ;
  380.         FSClose ( ref ) ;
  381.         DisposeHandle ( text ) ;
  382.     }
  383.     HUnlock ( text ) ;
  384.  
  385.     MungeHandle(text, vRef, parID, isTemplateDefn);
  386.  
  387.     DisposeHandle ( text ) ;
  388.     if ( err ) {
  389.         ErrMsg ( "\pClosing" , fn , err ) ;
  390.     }
  391.     
  392.     if (!isTemplateDefn)
  393.         Message ( "\p DONE\r" ) ;
  394. }
  395.  
  396.  
  397. void
  398. MungeFolder ( long parID ) {
  399.  
  400. short ix ;
  401.  
  402.     for ( ix = 1 ; ix > 0 ; ix ++ ) {
  403.         rec . hFileInfo . ioCompletion = 0L ;
  404.         rec . hFileInfo . ioFVersNum = 0 ;
  405.         rec . hFileInfo . ioNamePtr = name ;
  406.         rec . hFileInfo . ioVRefNum = vRefNum ;
  407.         rec . hFileInfo . ioDirID = parID ;
  408.         rec . hFileInfo . ioFDirIndex = ix ;
  409.         err = PBGetCatInfoAsync ( & rec ) ;
  410.         do {
  411.             Idle ( ) ;
  412.         } while ( rec . hFileInfo . ioResult == 1 ) ;
  413.         err = rec . hFileInfo . ioResult ;
  414.         if ( err ) {
  415.             break ;
  416.         }
  417.         if ( rec . hFileInfo . ioFlAttrib & 0x10 ) { /* Folder */
  418.             CopyP ( "\p\r•Entering Folder " , str ) ;
  419.             ConcP ( str , name ) ;
  420.             ConcP ( str , "\p\r" ) ;
  421.             Message ( str ) ;
  422.             MungeFolder ( rec . hFileInfo . ioDirID ) ;
  423.             Message ( "\p---- Leaving folder ----\r\r" ) ;
  424.         } else if ( rec . hFileInfo . ioFlFndrInfo . fdType == 'TEXT' ) {
  425.             MungeFile ( vRefNum , parID , name , false ) ;
  426.         }
  427.     }
  428. }
  429.